import { Inject, Injectable } from '@angular/core';
import { Observable } from 'rxjs';
import { REST_URL } from '../app.component';
import { URLConst } from '../consts/url-const';
import { ApiResult } from '../models/api.result';
import { AddDeptParam } from '../models/param/add-dept.param';
import { DeptQueryParam } from '../models/param/dept-query.param';
import { IntIdParam } from '../models/param/int-id.param';
import { MenuQueryParam } from '../models/param/menu-query.param';
import { RoleQueryParam } from '../models/param/role-query.param';
import { RoleUserQueryParam } from '../models/param/role-user-query.param';
import { UserQueryParam } from '../models/param/user-query.param';
import { DeptDto } from '../models/sys/dept.dto';
import { MenuDto } from '../models/sys/menu.dto';
import { RoleMenuDto } from '../models/sys/role-menu.dto';
import { RoleDto } from '../models/sys/role.dto';
import { UserDto } from '../models/sys/user.dto';
import { HttpService } from './http.service';
import { AddRoleParam } from '../models/param/add-role.param';
import { DictDto } from '../models/sys/dict.dto';
import { AddMenuParam } from '../models/param/add-menu.param';
import { AddUserParam } from '../models/param/add-user.param';
import { UpdateUserParam } from '../models/param/update-user.param';
import { UserPassword } from '../models/bo/user-password';
import { UserPermParam } from '../models/param/user-perm.param';
import { UpdateRoleParam } from '../models/param/update-role.param';
import { UpdateMenuParam } from '../models/param/update-menu.param';
import { UpdateDeptParam } from '../models/param/update-dept.param';
import { RoleDataScopeParam } from '../models/param/role-data-scope.param';
import { EndUserQueryParam } from '../models/param/end-user-query.param';
import { EndUserDto } from '../models/sys/end-user.dto';
import { GroupQueryParam } from '../models/param/group-query.param';
import { GroupDto } from '../models/sys/group.dto';
import { AddGroupTypeParam } from '../models/param/add-group-type.param';
import { AddGroupParam } from '../models/param/add-group.param';
import { PageParam } from '../models/param/page.param';
import { UpdateGroupTypeParam } from '../models/param/update-group-type.param';
import { UserInfoDto } from '../models/sys/user-info.dto';
import { GroupTypeDto } from '../models/sys/group-type.dto';

@Injectable({
  providedIn: 'root'
})
export class ApiService {

  constructor(private httpService: HttpService,
    @Inject(REST_URL) private baseUrl: string) { }

    logout(): Observable<object> {
      const url = this.baseUrl + URLConst.LOGOUT_URL;
      return this.httpService.get(url);
    }

    // Menu
    getMenuTree(param?: MenuQueryParam): Observable<ApiResult<MenuDto[]>> {
      const url = this.baseUrl + URLConst.MENU_TREE;
      if (param == null) {
        return this.httpService.get<ApiResult<MenuDto[]>>(url);
      } else {
        console.log(`ready to get menu tree : ${url}`);
        return this.httpService.getWithParam<ApiResult<MenuDto[]>>(url, param);
      }
    }

    getMenuTreePage(param?: MenuQueryParam): Observable<ApiResult<MenuDto[]>> {
      const url = this.baseUrl + URLConst.MENU_TREE_PAGE;
      if (param == null) {
        return this.httpService.get<ApiResult<MenuDto[]>>(url);
      } else {
        console.log(`ready to get menu tree page : ${url}`);
        return this.httpService.getWithParam<ApiResult<MenuDto[]>>(url, param);
      }
    }

    getRoleMenu(param: IntIdParam): Observable<ApiResult<RoleMenuDto[]>> {
      const url = this.baseUrl + URLConst.ROLE_MENU;
      return this.httpService.getWithParam(url, param);
    }

    addMenu(param: AddMenuParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.MENU_PATH;
      return this.httpService.post(url, param);
    }

    deleteMenu(id: number): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.MENU_PATH + "/" + id;
      return this.httpService.delete(url);
    }

    updateMenu(param: UpdateMenuParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.MENU_PATH;
      return this.httpService.putWithBody(url, param);
    }

    // Roles
    getRoleList(param: RoleQueryParam): Observable<ApiResult<RoleDto[]>> {
      const url = this.baseUrl + URLConst.ROLE_LIST;
      return this.httpService.getWithParam(url, param);
    }

    getRoleDetail(roleId: number): Observable<ApiResult<RoleDto>> {
      const url = this.baseUrl + URLConst.ROLE_PATH + "/" + roleId;
      return this.httpService.get(url);
    }

    addRole(param: AddRoleParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.ROLE_PATH;
      return this.httpService.post(url, param);
    }

    updateRole(param: UpdateRoleParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.ROLE_PATH;
      return this.httpService.putWithBody(url, param);
    }

    updateAuthDataScope(param: RoleDataScopeParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.ROLE_DATA_SCOPE;
      return this.httpService.putWithBody(url, param);
    }

    deleteRole(id: number): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.ROLE_PATH + "/" + id;
      return this.httpService.delete(url);
    }

    // Employee
    getUserList(param: UserQueryParam): Observable<ApiResult<UserDto[]>> {
      const url = this.baseUrl + URLConst.USER_LIST;
      return this.httpService.getWithParam(url, param);
    }

    getUserDetail(userId: number): Observable<ApiResult<UserDto>> {
      const url = this.baseUrl + URLConst.USER_PATH + "/" + userId;
      return this.httpService.get(url);
    }

    getUsersByRole(param: RoleUserQueryParam): Observable<ApiResult<UserDto[]>> {
      const url = this.baseUrl + URLConst.USER_BY_ROLE;
      return this.httpService.getWithParam(url, param);
    }

    getUserInfo(): Observable<ApiResult<UserInfoDto>> {
      const url = this.baseUrl + URLConst.USER_INFO;
      return this.httpService.get(url);
    }

    addUser(param: AddUserParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.USER_PATH;
      return this.httpService.post(url, param);
    }

    updateUser(param: UpdateUserParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.USER_PATH;
      return this.httpService.putWithBody(url, param);
    }

    resetUserPassword(param: UserPassword): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.RESET_PASSWORD;
      return this.httpService.putWithBody(url, param);
    }

    assignRoles(param: UserPermParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.USER_ASSIGN_ROLES;
      return this.httpService.putWithBody(url, param);
    }

    deleteUser(id: number): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.USER_PATH + "/";
      return this.httpService.deleteByIds(url, [id]);
    }

    // EndUser
    getEndUserList(param: EndUserQueryParam): Observable<ApiResult<EndUserDto[]>> {
      const url = this.baseUrl + URLConst.END_USER_LIST;
      return this.httpService.getWithParam(url, param);
    }

    // Depts
    getDeptTree(param: DeptQueryParam): Observable<ApiResult<DeptDto[]>> {
      const url = this.baseUrl + URLConst.DEPT_TREE;
      return this.httpService.getWithParam(url, param);
    }

    addDept(param: AddDeptParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.DEPT_PATH;
      return this.httpService.post(url, param);
    }

    updateDept(param: UpdateDeptParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.DEPT_PATH;
      return this.httpService.putWithBody(url, param);
    }

    deleteDept(id: number): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.DEPT_PATH + "/" + id;
      return this.httpService.delete(url);
    }

    // Types
    getMenuType(): Observable<ApiResult<DictDto[]>> {
      const url = this.baseUrl + URLConst.ENUM_MENU_TYPE;
      return this.httpService.get(url);
    }

    getSexType(): Observable<ApiResult<DictDto[]>> {
      const url = this.baseUrl + URLConst.ENUM_SEX;
      return this.httpService.get(url);
    }

    getDataScopes(): Observable<ApiResult<DictDto[]>> {
      const url = this.baseUrl + URLConst.ENUM_DATA_SCOPE;
      return this.httpService.get(url);
    }

    // Group
    getGroupList(param: GroupQueryParam): Observable<ApiResult<GroupDto[]>> {
      const url = this.baseUrl + URLConst.GROUP_LIST;
      return this.httpService.getWithParam(url, param);
    }

    getGroupsByRole(param: IntIdParam): Observable<ApiResult<GroupDto[]>> {
      const url = this.baseUrl + URLConst.GROUP_BY_ROLE;
      return this.httpService.getWithParam(url, param);
    }

    addGroupType(param: AddGroupTypeParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.GROUP_TYPE;
      return this.httpService.post(url, param);
    }

    getGroupTypeDetail(typeId: number): Observable<ApiResult<GroupTypeDto>> {
      const url = this.baseUrl + URLConst.GROUP_TYPE + "/" + typeId;
      return this.httpService.get(url);
    }

    updateGroupType(param: UpdateGroupTypeParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.GROUP_TYPE;
      return this.httpService.putWithBody(url, param);
    }

    deleteGroupType(id: number): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.GROUP_TYPE + "/" + id;
      return this.httpService.delete(url);
    }

    deleteGroup(id: number): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.GROUP_PATH + "/" + id;
      return this.httpService.delete(url);
    }
    
    addGroup(param: AddGroupParam): Observable<ApiResult<boolean>> {
      const url = this.baseUrl + URLConst.GROUP_PATH;
      return this.httpService.post(url, param);
    }

    getGroupTypeList(param: PageParam): Observable<ApiResult<DictDto[]>> {
      const url = this.baseUrl + URLConst.GROUP_TYPES;
      return this.httpService.getWithParam(url, param);
    }
}
